<template>
  <div id="layout">
    <!-- 父传子 属性名需要用连字符- ,一般不要用小驼峰命名 -->
    <lay-header
      :control-collapse="isCollapse"
      @updateCollapse="updateCollapse"
    ></lay-header>
    <el-container>
      <el-aside :width="isCollapse ? '64px' : '200px'">
        <el-menu
          unique-opened
          :collapse="isCollapse"
          :collapse-transition="false"
          router
          :default-active="$route.path"
        >
          <lay-sub-menu
            v-for="(routeItem, index) in routes"
            :key="index"
            :route="routeItem"
            @upActTabs="upActTabs"
            @upOpenTabs="upOpenTabs"
          ></lay-sub-menu>
        </el-menu>
      </el-aside>
      <el-main>
        <!-- tabs标签页 -->
        <!-- 
              1. 侧边栏和tabs属于同步关系
              2. 侧边栏点击时会动态添加tabs的数量，同时tabs也可以关闭标签页（标签页最后一个是不能被关闭的）
              3. 用缓存记住用户的路由操作（未优化）
              4. 删除tabs
           -->
        <el-tabs
          v-model="currentTab"
          type="card"
          closable
          @tab-click="toTabs"
          @tab-remove="removeTab"
        >
          <el-tab-pane
            v-for="item in tableTabs"
            :key="item.name"
            :label="item.meta.title"
            :name="item.name"
          >
          </el-tab-pane>
        </el-tabs>
        <!--  -->
        <keep-alive>
          <!-- 继续匹配孩子组件 -->
          <router-view v-if="$route.meta.keepAlive"></router-view
        ></keep-alive>
        <router-view v-if="!$route.meta.keepAlive"></router-view>
      </el-main>
    </el-container>
  </div>
</template>

<script>
import LayHeader from './components/LayHeader'
import LaySubMenu from './components/LaySubMenu'
export default {
  components: {
    LayHeader,
    LaySubMenu,
  },
  data() {
    return {
      // 是否折叠
      isCollapse: false,
      // 默认打开的标签页 /->notice-center
      currentTab: this.$route.name,
      // 打开的标签数组
      tableTabs: [],
    }
  },
  created() {
    // data 、computed、methods、watch都能用了，但是唯独dom元素操作不了
  },
  mounted() {
    // 如果说tabsOpen,默认打开noticeCenter
    this.tableTabs = this.defaultTabs
  },
  methods: {
    // 子传父的值，更改折叠的状态
    updateCollapse(data) {
      this.isCollapse = data
    },
    /**
     *  点击触发跳转路由
     */
    toTabs(route) {
      this.isExistName(route.name)
    },
    /**
     * 判断路由是否重复name
     */
    isExistName(routeName) {
      if (this.$route.name !== routeName) {
        this.$router.push({name: routeName})
      }
    },
    /**
     * 动态删除tabs标签
     */
    removeTab(targetName) {
      // 阻断操作
      if (this.tableTabs.length <= 1) {
        // element关闭所有提示框
        this.$message.closeAll()
        return this.$message({
          message: '大哥，别删了，再删就没了',
          type: 'warning',
        })
      }
      // targetName是要关闭的name
      console.log(targetName)
      // 这是所有的标签页数组
      let tabs = this.tableTabs
      // 选中的标签页的name
      let activeName = this.currentTab
      // 判断当前选中的和要删除的是一个不
      if (activeName === targetName) {
        tabs.forEach((tab, index) => {
          // index 1
          if (tab.name === targetName) {
            // 找下一个标签页的对象  tabs[index + 1]  ,没有下一个元素undefined
            // tabs[index - 1] 找数组中的上一个元素。为了能让它找到，必须做一步阻断操作（数组必须得留一个对象）
            let nextTab = tabs[index + 1] || tabs[index - 1]
            if (nextTab) {
              // 让tabs直接选中
              activeName = nextTab.name
              this.isExistName(nextTab.name)
            }
          }
        })
      }
      // 更改当前的选中
      this.currentTab = activeName

      // 重新渲染的操作      赋值给this.defaultTabs执行了set操作
      this.tableTabs = this.defaultTabs = tabs.filter(
        tab => tab.name !== targetName
      )
    },

    /**
     * 侧边栏传值,更新tabs高亮
     */
    upActTabs(name) {
      this.currentTab = name
    },
    /**
     * 侧边栏传值，
     * tabs是整个数组
     */
    upOpenTabs(tabs) {
      this.tableTabs = tabs
    },
  },
  // 计算属性
  computed: {
    // 获取所有的路由表
    routes() {
      return this.$router.options.routes
    },
    // 这个结果受多种情况（多个值）影响，需要去进一步做逻辑计算
    defaultTabs: {
      // get 获取值
      get() {
        // 1. 如果说用户它以前有操作记录
        const local = localStorage.getItem('openTabs')
        let openTabs = []
        const {path, meta, name} = this.$route
        // 判断是否有缓存
        if (local) {
          // 有缓存
          openTabs = JSON.parse(local)
          // 判断路由数组/缓存中是否存在当前打开的路由
          if (!openTabs.some(item => item.name === this.$route.name)) {
            openTabs.push({path, meta, name})
          }
        } else {
          // 这个子孩子代表的是所有的侧边栏路由
          const allChild = []
          this.routes.forEach(item => {
            if (item.children) {
              allChild.push(...item.children)
            }
          })

          // 取路由中meta/tabsOpen 为true，系统默认想打开的
          openTabs = allChild.filter(item => item.meta.tabsOpen)

          // 模拟用户首次进入页面，没有默认打开的选项卡
          if (!openTabs.length) {
            openTabs.push({path, meta, name})
          }
        }
        localStorage.setItem('openTabs', JSON.stringify(openTabs))
        return openTabs
      },

      // set 设置值。 当defaultTabs被别人赋值的时候 ->  this.defaultTabs = xxxx;
      set(value) {
        localStorage.setItem('openTabs', JSON.stringify(value))
      },
    },
  },
}
</script>

<style lang="less" scoped>
#layout {
  .el-main,
  .el-aside {
    //   vh -> view height
    height: calc(100vh - 60px);
  }
}
.el-aside {
  border-right: 1px solid @lineColor;
  transition: width 0.3s;
  &::-webkit-scrollbar {
    display: none;
  }
  .el-menu {
    width: 100%;
    border-right: 0;
  }
  .is-active .el-submenu__title {
    color: @baseColor;
    i {
      color: @baseColor;
    }
  }
}

.el-main {
  color: #333;
  padding: 0;
  overflow: hidden;
  .el-tabs {
    padding: 15px 20px 0 20px;
    ::v-deep .el-tabs__nav {
      border: none;
      border-radius: 0;
    }
    ::v-deep .el-tabs__item {
      border: 1px solid @lineColor;
      background: #f5f7fa;
      margin: 0 2px;
      border-radius: 4px 4px 0 0;
      &.is-active {
        border-bottom: 0;
        background-color: #fff;
      }
    }
  }
}
</style>
